package com.hitqz.robot.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.cache.Cache;
import com.google.common.collect.Lists;
import com.hitqz.robot.api.common.dto.mapArea.CalculateAreaMapDto;
import com.hitqz.robot.api.common.entity.MapArea;
import com.hitqz.robot.api.common.entity.MapAreaPos;
import com.hitqz.robot.api.common.entity.Robot;
import com.hitqz.robot.api.common.util.CacheNameUtil;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotMapAreaDto;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotMapAreaPosDto;
import com.hitqz.robot.biz.business.util.CalculateUtil;
import com.hitqz.robot.biz.mapper.MapAreaMapper;
import com.hitqz.robot.biz.service.AreaActionService;
import com.hitqz.robot.biz.service.MapAreaPosService;
import com.hitqz.robot.biz.service.MapAreaService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.netty.service.Send2ServerService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xupkun
 * @date 2024/6/3
 */
@Service
@AllArgsConstructor
@Slf4j
public class MapAreaServiceImpl extends ServiceImpl<MapAreaMapper, MapArea> implements MapAreaService {
    private final Send2ServerService send2ServerService;

    private final RobotService robotService;

    private final MapAreaPosService mapAreaPosService;

    private final AreaActionService areaActionService;

    @Override
    public List<MapArea> findMapAreaActions(String action) {
        return baseMapper.findMapAreaByAction(action);
    }

    @Override
    public void asyncMapArea() {
        Robot robot = robotService.getDefaultRobot();
        List<MapArea> mapAreas = baseMapper.selectList(null);
        for (MapArea mapArea : mapAreas) {
            RobotMapAreaDto robotMapAreaDto = new RobotMapAreaDto();
            robotMapAreaDto.setClientId(robot.getRobotSn());
            BeanUtil.copyProperties(mapArea, robotMapAreaDto, false);
            List<MapAreaPos> mapAreaPos = mapAreaPosService.list(Wrappers.<MapAreaPos>lambdaQuery().eq(MapAreaPos::getAreaId, mapArea.getId()));
            if (CollectionUtil.isNotEmpty(mapAreaPos)) {
                List<RobotMapAreaPosDto> robotMapPosDtos = Lists.newArrayList();
                mapAreaPos.forEach(t-> {
                    RobotMapAreaPosDto dto = new RobotMapAreaPosDto();
                    BeanUtil.copyProperties(t, dto, false);
                    robotMapPosDtos.add(dto);
                });
                robotMapAreaDto.setAreaPos(robotMapPosDtos);
            }
            send2ServerService.syncRobotMapAreaInfo(0, robotMapAreaDto);
        }
    }

    @Override
    public void initMapArea() {
        log.info("初始化地图区域数据");
        Robot robot = robotService.getDefaultRobot();
        if (robot == null || StrUtil.isEmpty(robot.getMapCode())) {
            log.warn("机器人数据为空或地图编码为空，无法初始化地图区域数据");
            return;
        }

        Cache<Long, CalculateAreaMapDto> cache = SpringUtil.getBean(CacheNameUtil.CACHE_MAP_AREA);

        // 清除所有缓存条目
        cache.invalidateAll();
        log.info("已清除所有缓存数据，当前缓存大小: {}", cache.size());

        try {
            List<MapArea> mapAreas = this.list(Wrappers.<MapArea>lambdaQuery()
                    .eq(MapArea::getStatus, 1)
                    .eq(MapArea::getMapCode, robot.getMapCode()));
            // 收集所有需要查询的areaIds
            List<Long> areaIds = mapAreas.stream().map(MapArea::getId).collect(Collectors.toList());
            // 查询所有相关的位置信息
            List<MapAreaPos> allAreaPos = mapAreaPosService.list(Wrappers.<MapAreaPos>lambdaQuery()
                    .in(MapAreaPos::getAreaId, areaIds));
            // 将位置信息按areaId分组
            Map<Long, List<MapAreaPos>> areaPosByAreaId = allAreaPos.stream()
                    .collect(Collectors.groupingBy(MapAreaPos::getAreaId));
            for (MapArea area : mapAreas) {
                List<MapAreaPos> areaPos = areaPosByAreaId.getOrDefault(area.getId(), Collections.emptyList());
                CalculateAreaMapDto dto = new CalculateAreaMapDto();
                dto.setMapArea(area);
                dto.setMapAreaPosList(areaPos);
                dto.setPolygon(CalculateUtil.createAreaPolygon(areaPos));
                cache.put(area.getId(), dto);
            }
        } catch (Exception e) {
            log.error("初始化地图区域数据时发生错误: {}, 地图编码: {}", e.getMessage(), robot.getMapCode(), e);
            // 可以添加重试机制或其他错误处理逻辑
        }

        log.info("结束初始化地图区域数据" + cache.size());
    }


}
